From 12bed57ae00d8bf746ea0b089e2c116dc9d0aa4f Mon Sep 17 00:00:00 2001 From: robertl Date: Wed, 4 Dec 2002 17:44:45 +0000 Subject: [PATCH] Update from Josh. Get the extension list dynamically instead of from internal table. --- gpsbabel/win32/gpsbabelfront_mainform.dfm | 48 ++- gpsbabel/win32/gpsbabelfront_mainform.pas | 351 ++++++++++++++++------ 2 files changed, 298 insertions(+), 101 deletions(-) diff --git a/gpsbabel/win32/gpsbabelfront_mainform.dfm b/gpsbabel/win32/gpsbabelfront_mainform.dfm index 6abfda6e8..7721ba5c3 100644 --- a/gpsbabel/win32/gpsbabelfront_mainform.dfm +++ b/gpsbabel/win32/gpsbabelfront_mainform.dfm @@ -3,7 +3,7 @@ object FormGPSBabelFront: TFormGPSBabelFront Top = 103 BorderStyle = bsDialog Caption = 'GPSBabel GUI Frontend' - ClientHeight = 212 + ClientHeight = 312 ClientWidth = 369 Color = clBtnFace Font.Charset = DEFAULT_CHARSET @@ -16,12 +16,12 @@ object FormGPSBabelFront: TFormGPSBabelFront OnCreate = FormCreate DesignSize = ( 369 - 212) + 312) PixelsPerInch = 96 TextHeight = 13 object Label1: TLabel Left = 8 - Top = 192 + Top = 292 Width = 250 Height = 13 Anchors = [akLeft, akBottom] @@ -43,11 +43,32 @@ object FormGPSBabelFront: TFormGPSBabelFront end object Bevel1: TBevel Left = -3 - Top = 185 + Top = 285 Width = 380 Height = 2 Anchors = [akLeft, akBottom] end + object Label4: TLabel + Left = 16 + Top = 104 + Width = 35 + Height = 13 + Caption = 'Format:' + end + object Label5: TLabel + Left = 16 + Top = 40 + Width = 35 + Height = 13 + Caption = 'Format:' + end + object Label6: TLabel + Left = 8 + Top = 168 + Width = 33 + Height = 13 + Caption = 'Result:' + end object comboInput: TComboBox Left = 64 Top = 40 @@ -82,7 +103,7 @@ object FormGPSBabelFront: TFormGPSBabelFront end object btnProcess: TButton Left = 288 - Top = 152 + Top = 136 Width = 75 Height = 25 Caption = 'Process' @@ -115,12 +136,21 @@ object FormGPSBabelFront: TFormGPSBabelFront TabOrder = 4 OnClick = btnOutputClick end + object memoStdErr: TMemo + Left = 64 + Top = 168 + Width = 297 + Height = 113 + Color = clBtnHighlight + ReadOnly = True + TabOrder = 8 + end object OpenDialogInput: TOpenDialog - Left = 80 - Top = 8 + Left = 248 + Top = 192 end object SaveDialogOutput: TSaveDialog - Left = 80 - Top = 72 + Left = 248 + Top = 240 end end diff --git a/gpsbabel/win32/gpsbabelfront_mainform.pas b/gpsbabel/win32/gpsbabelfront_mainform.pas index 7dd7a9d94..4507e12ab 100644 --- a/gpsbabel/win32/gpsbabelfront_mainform.pas +++ b/gpsbabel/win32/gpsbabelfront_mainform.pas @@ -1,6 +1,6 @@ { - Copyright (C) 2002 Josh M. McKee, geo@mrsnazz.com + Copyright (C) 2002 Josh M. McKee, mrsnazz@users.sourceforge.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,6 +18,16 @@ } +{ + 1.0.0 JMc First release + 1.0.1 JMc - Switched to using AddFormat for populating the formats table + - Updated formats table to include currently supported formats + - Switched to using CreateProcess rather than WinExec, so that + we can display data from stderr to the user. + 1.0.2 JMc - Added LoadFormats to call the new -^ switch, to dynamically + load the supported formats from gpsbabel.exe. +} + unit gpsbabelfront_mainform; interface @@ -26,12 +36,9 @@ uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls; -const - FormatCount = 18; - type - TFormat = record - sType:string; // type to be passed to GPSBabel + TFormat = record + sType:string; // type to be passed to GPSBabel sExt:string; // default file extension sDesc:string; // description of format end; @@ -51,15 +58,20 @@ type btnOutput: TButton; OpenDialogInput: TOpenDialog; SaveDialogOutput: TSaveDialog; + Label4: TLabel; + Label5: TLabel; + memoStdErr: TMemo; + Label6: TLabel; procedure FormCreate(Sender: TObject); procedure btnInputClick(Sender: TObject); procedure btnOutputClick(Sender: TObject); procedure btnProcessClick(Sender: TObject); - private - { Private declarations } public - { Public declarations } - formats:array[0..FormatCount-1] of TFormat; + formats:array of TFormat; + nFormatCount:integer; + + procedure LoadFormats; + procedure AddFormat(sType,sExt,sDesc:string); procedure PopulateCombos; procedure PopulateDialogs; @@ -72,29 +84,40 @@ implementation {$R *.dfm} +procedure TFormGPSBabelFront.AddFormat(sType,sExt,sDesc:string); +begin + SetLength(formats,nFormatCount+1); + + formats[nFormatCount].sType := sType; + formats[nFormatCount].sExt := sExt; + formats[nFormatCount].sDesc := sDesc; + + inc(nFormatCount); +end; + procedure TFormGPSBabelFront.PopulateCombos; var - i:integer; + i:integer; begin - for i:=0 to FormatCount-1 do begin - comboInput.items.add(formats[i].sDesc); + for i:=0 to nFormatCount-1 do begin + comboInput.items.add(formats[i].sDesc); comboOutput.items.add(formats[i].sDesc); end; end; procedure TFormGPSBabelFront.PopulateDialogs; var - i:integer; + i:integer; begin - OpenDialogInput.Filter := ''; + OpenDialogInput.Filter := ''; SaveDialogOutput.Filter := ''; - for i:=0 to FormatCount-1 do begin - if (formats[i].sExt<>'') then begin - OpenDialogInput.Filter := OpenDialogInput.Filter + formats[i].sDesc + ' (*.' + - formats[i].sExt + ')|*.' + uppercase(formats[i].sExt) + '|'; + for i:=0 to nFormatCount-1 do begin + if (formats[i].sExt<>'') then begin + OpenDialogInput.Filter := OpenDialogInput.Filter + formats[i].sDesc + ' (*.' + + formats[i].sExt + ')|*.' + uppercase(formats[i].sExt) + '|'; - SaveDialogOutput.Filter := SaveDialogOutput.Filter + formats[i].sDesc + ' (*.' + - formats[i].sExt + ')|*.' + uppercase(formats[i].sExt) + '|'; + SaveDialogOutput.Filter := SaveDialogOutput.Filter + formats[i].sDesc + ' (*.' + + formats[i].sExt + ')|*.' + uppercase(formats[i].sExt) + '|'; end; end; @@ -104,112 +127,256 @@ end; procedure TFormGPSBabelFront.FormCreate(Sender: TObject); begin - formats[0].sType := 'geo'; - formats[0].sExt := 'loc'; - formats[0].sDesc := 'Geocaching.com .loc'; - formats[1].sType := 'gpsman'; - formats[1].sExt := ''; - formats[1].sDesc := 'GPSman'; - formats[2].sType := 'gpx'; - formats[2].sExt := 'gpx'; - formats[2].sDesc := 'GPX XML'; - formats[3].sType := 'magellan'; - formats[3].sExt := ''; - formats[3].sDesc := 'Magellan protocol'; - formats[4].sType := 'mapsend'; - formats[4].sExt := ''; - formats[4].sDesc := 'Magellan Mapsend'; - formats[5].sType := 'pcx'; - formats[5].sExt := 'pcx'; - formats[5].sDesc := 'Garmin PCX5'; - formats[6].sType := 'mapsource'; - formats[6].sExt := ''; - formats[6].sDesc := 'Garmin Mapsource'; - formats[7].sType := 'gpsutil'; - formats[7].sExt := ''; - formats[7].sDesc := 'gpsutil'; - formats[8].sType := 'tiger'; - formats[8].sExt := ''; - formats[8].sDesc := 'U.S. Census Bureau Tiger Mapping Service'; - formats[9].sType := 'csv'; - formats[9].sExt := 'csv'; - formats[9].sDesc := 'Comma separated values'; - formats[10].sType := 'dna'; - formats[10].sExt := 'dna'; - formats[10].sDesc := 'Navitrak DNA marker format'; - formats[11].sType := 'psp'; - formats[11].sExt := 'psp'; - formats[11].sDesc := 'MS PocketStreets 2002 Pushpin'; - formats[12].sType := 'cetus'; - formats[12].sExt := 'pdb'; - formats[12].sDesc := 'Cetus for Palm/OS'; - formats[13].sType := 'gpspilot'; - formats[13].sExt := ''; - formats[13].sDesc := 'GPSPilot Tracker for Palm/OS'; - formats[14].sType := 'garmin'; - formats[14].sExt := ''; - formats[14].sDesc := 'Garmin serial protocol'; - formats[15].sType := 'mxf'; - formats[15].sExt := 'mxf'; - formats[15].sDesc := 'MapTech Exchange Format'; - formats[16].sType := 'holux'; - formats[16].sExt := 'wpo'; - formats[16].sDesc := 'Holux (gm-100) .wpo Format'; - formats[17].sType := 'ozi'; - formats[17].sExt := 'ozi'; - formats[17].sDesc := 'OziExplorer Waypoint'; + nFormatCount := 0; + // load formats from GPSBabel.exe + LoadFormats; + + if nFormatCount = 0 then begin + ShowMessage('Unable to load format list from GPSBabel.exe. Default format list is being used instead.'); + + // add the default formats + AddFormat('geo','loc','Geocaching.com .loc'); + AddFormat('gpsman','','GPSman'); + AddFormat('gpx','gpx','GPX XML'); + AddFormat('magellan','','Magellan protocol'); + AddFormat('mapsend','','Magellan Mapsend'); + AddFormat('pcx','pcx','Garmin PCX5'); + AddFormat('mapsource','','Garmin Mapsource'); + AddFormat('gpsutil','','gpsutil'); + AddFormat('tiger','','U.S. Census Bureau Tiger Mapping Service'); + AddFormat('csv','csv','Comma seperated values'); + AddFormat('xmap','','Delorme Topo USA4/XMap Conduit'); + AddFormat('dna','dna','Navitrak DNA marker format'); + AddFormat('psp','psp','MS PocketStreets 2002 Pushpin'); + AddFormat('cetus','','Cetus for Palm/OS'); + AddFormat('gpspilot','','GPSPilot Tracker for Palm/OS'); + AddFormat('magnav','','Magellan NAV Companion for PalmOS'); + AddFormat('garmin','','Garmin serial protocol'); + AddFormat('mxf','mxf','MapTech Exchange Format'); + AddFormat('holux','wpo','Holux (gm-100) .wpo Format'); + AddFormat('ozi','ozi','OziExplorer Waypoint'); + AddFormat('tpg','tpg','National Geographic Topo .tpg'); + AddFormat('tmpro','tmpro','TopoMapPro Places File'); + end; + + // Set up the dropdown lists and open/save dialog filters using the formats PopulateCombos; PopulateDialogs; end; procedure TFormGPSBabelFront.btnInputClick(Sender: TObject); var - sExt:string; + sExt:string; i:integer; begin - if opendialoginput.Execute then begin - editInput.Text := opendialoginput.filename; + if opendialoginput.Execute then begin + editInput.Text := opendialoginput.filename; sExt := uppercase(ExtractFileExt(editInput.text)); - for i := 0 to FormatCount-1 do begin - if '.' + uppercase(formats[i].sExt) = sExt then comboInput.ItemIndex := i; + for i := 0 to nFormatCount-1 do begin + if '.' + uppercase(formats[i].sExt) = sExt then comboInput.ItemIndex := i; end; end; end; procedure TFormGPSBabelFront.btnOutputClick(Sender: TObject); var - sExt:string; + sExt:string; i:integer; begin - if savedialogoutput.Execute then begin - editOutput.Text := savedialogoutput.filename; + if savedialogoutput.Execute then begin + editOutput.Text := savedialogoutput.filename; sExt := uppercase(ExtractFileExt(editOutput.text)); - for i := 0 to FormatCount-1 do begin - if '.' + uppercase(formats[i].sExt) = sExt then comboOutput.ItemIndex := i; + for i := 0 to nFormatCount-1 do begin + if '.' + uppercase(formats[i].sExt) = sExt then comboOutput.ItemIndex := i; end; end; end; +procedure TFormGPSBabelFront.LoadFormats; +var + sIgnoreShort:string; + sCmd:string; + f:file; + Buffer:array[0..255] of char; + hRead,hWrite:THandle; + StartupInfo:TStartupInfo; + ProcessInfo:TProcessInformation; + saAttr:TSecurityAttributes; + OutSt:TMemoryStream; + dwRead:DWord; + dwExitCode:cardinal; + overlapped:TOverlapped; + slstFormats:TStringList; + i:integer; + + procedure ExtractFormat(sFormat:string); + var + toks:array[0..2] of string; + i,nTok,nLen:integer; + begin + i := 1; + nTok := 0; + toks[0] := ''; + toks[1] := ''; + toks[2] := ''; + nLen := length(sFormat); + while ((i<=nLen) and (nTok<3)) do begin + if sFormat[i]=#9 then begin + inc(nTok); + end else begin + toks[nTok] := toks[nTok] + sFormat[i]; + end; + inc(i); + end; + {showmessage(toks[0]); + showmessage(toks[1]); + showmessage(toks[2]);} + + AddFormat(toks[0],toks[1],toks[2]); + end; + +begin + slstFormats := TStringList.Create; + + sCmd := 'GPSBabel -^'; + + memoStdErr.lines.clear; + + saAttr.nLength := sizeof(TSECURITYATTRIBUTES); + saAttr.bInheritHandle := true; + saAttr.lpSecurityDescriptor := nil; + + if not CreatePipe(hRead, hWrite,@saAttr,0) then begin + ShowMessage('Unable to create pipe!'); + Exit; + end; + + AllocConsole; + + FillChar(StartupInfo,Sizeof(StartupInfo),#0); + StartupInfo.cb := Sizeof(StartupInfo); + StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; + StartupInfo.wShowWindow := SW_HIDE and SW_SHOWMINNOACTIVE; + StartupInfo.hStdInput := GetStdHandle(STD_INPUT_HANDLE); + StartupInfo.hStdOutput:= hWrite; + StartupInfo.hStdError := hWrite; + + if not CreateProcess(nil,pchar(sCmd),nil,nil,true,CREATE_NEW_CONSOLE,nil,nil,StartupInfo,ProcessInfo) then begin + ShowMessage('Unable to execute GPSBabel.exe.') + end else begin + while (WaitforSingleObject(ProcessInfo.hProcess,0)) <> WAIT_OBJECT_0 do; + + PeekNamedPipe(hRead,nil,0,nil,@dwRead,nil); + + if dwRead>0 then begin + OutSt := TMemoryStream.Create; + + repeat + if ReadFile(hRead, Buffer, 80, dwRead, nil) then begin + OutSt.WriteBuffer(Buffer, dwRead) + end; + until dwRead<>80; + + OutSt.Seek(0,0); + slstFormats.LoadFromStream(OutSt); + for i:=0 to slstFormats.count-1 do begin + ExtractFormat(slstFormats[i]); + end; + OutSt.Free; + end else memoStdErr.lines.add('Command executed successfully.'); + end; + + CloseHandle(hRead); CloseHandle(hWrite); + FreeConsole; +end; + procedure TFormGPSBabelFront.btnProcessClick(Sender: TObject); var - sIgnoreShort:string; + sIgnoreShort:string; sCmd:string; f:file; + Buffer:array[0..255] of char; + hRead,hWrite:THandle; + StartupInfo:TStartupInfo; + ProcessInfo:TProcessInformation; + saAttr:TSecurityAttributes; + OutSt:TMemoryStream; + dwRead:DWord; + dwExitCode:cardinal; + overlapped:TOverlapped; begin - if cbIgnoreShort.checked then sIgnoreShort := '-s' else sIgnoreShort := ''; + if (comboInput.ItemIndex)<0 then begin + ShowMessage('You must select the input file format.'); + exit; + end; + + if (comboOutput.ItemIndex)<0 then begin + ShowMessage('You must select the output file format.'); + exit; + end; + + if cbIgnoreShort.checked then sIgnoreShort := '-s' else sIgnoreShort := ''; + // The output file must exist, or else ExtractShortPathName will not function if not fileexists(editoutput.text) then begin - system.assign(f,editoutput.text); - system.rewrite(f); + system.assign(f,editoutput.text); + system.rewrite(f); system.close(f); end; + // Construct the command line to execute gpsbabel.exe. ExtractShortPathName + // is used to reduce any "long" file/directory names in the paths down to + // 8.3 dos format names (this removes spaces, etc). sCmd := 'GPSBabel '+sIgnoreShort+' -i '+formats[comboInput.itemindex].sType+' -f '+ - ExtractShortPathName(editInput.text)+' -o '+formats[comboOutput.itemindex].sType+' -F '+ - ExtractShortPathName(editOutput.text) + ' > result.txt'; + ExtractShortPathName(editInput.text)+' -o '+formats[comboOutput.itemindex].sType+' -F '+ + ExtractShortPathName(editOutput.text); + + memoStdErr.lines.clear; + + saAttr.nLength := sizeof(TSECURITYATTRIBUTES); + saAttr.bInheritHandle := true; + saAttr.lpSecurityDescriptor := nil; + + if not CreatePipe(hRead, hWrite,@saAttr,0) then begin + ShowMessage('Unable to create pipe!'); + Exit; + end; + + AllocConsole; + + FillChar(StartupInfo,Sizeof(StartupInfo),#0); + StartupInfo.cb := Sizeof(StartupInfo); + StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; + StartupInfo.wShowWindow := SW_HIDE and SW_SHOWMINNOACTIVE; + StartupInfo.hStdInput := GetStdHandle(STD_INPUT_HANDLE); + StartupInfo.hStdOutput:= hWrite; + StartupInfo.hStdError := hWrite; + + if not CreateProcess(nil,pchar(sCmd),nil,nil,true,CREATE_NEW_CONSOLE,nil,nil,StartupInfo,ProcessInfo) then begin + ShowMessage('Unable to execute GPSBabel.exe.') + end else begin + while (WaitforSingleObject(ProcessInfo.hProcess,0)) <> WAIT_OBJECT_0 do; + + PeekNamedPipe(hRead,nil,0,nil,@dwRead,nil); + + if dwRead>0 then begin + OutSt := TMemoryStream.Create; + + repeat + if ReadFile(hRead, Buffer, 80, dwRead, nil) then begin + OutSt.WriteBuffer(Buffer, dwRead) + end; + until dwRead<>80; + + OutSt.Seek(0,0); + memoStdErr.lines.LoadFromStream(OutSt); + OutSt.Free; + end else memoStdErr.lines.add('Command executed successfully.'); + end; - WinExec(pchar(sCmd),SW_SHOW); + CloseHandle(hRead); CloseHandle(hWrite); + FreeConsole; end; end. -- 2.30.2